<?php

declare(strict_types=1);

namespace App\Model\Service;

use App\Model\CallBase;
use App\Model\Guild\GuildHost;
use App\Model\Guild\GuildManage;
use App\Model\HostBlacklist;
use App\Model\HostPoolForNew;
use App\Model\Setting\SettingUserLevel;
use App\Model\User;
use App\Model\UserChat;
use App\Model\UserProfile;
use App\Model\VideoCall;
use App\Model\VoiceCall;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\DbConnection\Db;
use Psr\EventDispatcher\EventDispatcherInterface;
use Hyperf\Di\Annotation\Inject;

class CacheService
{
    /**
     * @Inject
     * @var EventDispatcherInterface
     */
    protected $dispatcher;

    public function flushCache($userId)
    {
        // $this->dispatcher->dispatch(new DeleteListenerEvent('user-update', [$userId]));
        return true;
    }

    /**
     * 无效的用户ID（拉黑，注销等，可扩展）
     * @Cacheable(prefix="invalid_user", ttl=3600, listener="invalid_user_update")
     */
    static function invalidUsers(): array
    {
        log_info(__METHOD__);
        $status = [User::STATUS_CANCELLATTED, User::STATUS_FREEZE];
        $userIds = User::whereIn('status', $status)->pluck('id')->toArray();
        return $userIds;
    }

    /**
     * 黑名单主播ID
     * @Cacheable(prefix="black_hosts", ttl=300, listener="black_hosts_update")
     */
    static function blackHosts(): array
    {
        log_info(__METHOD__);
        return HostBlacklist::getHostIds();
    }

    /**
     * 分渠道的主播ID
     * @Cacheable(prefix="channel_hosts", ttl=300, value="_#{channel}", listener="channel_hosts_update")
     */
    static function channelHosts($channel = ''): array
    {
        if (!$channel) return [];
        log_info(__METHOD__ . "=={$channel}");
        return Db::table('user_profile')->join('user', function ($join) use ($channel) {
            $where = [
                ['status', '=', User::STATUS_OK],
                // ['is_official', 0],
                ['role', UserProfile::ROLE_HOST],
            ];
            if (is_array($channel)) {
                $join->on('user.id', '=', 'user_profile.user_id')->whereIn('channel', $channel);
            } else {
                $where[] = ['channel', $channel];
                $join->on('user.id', '=', 'user_profile.user_id')->where($where);
            }
        })->pluck('channel', 'user_id')->toArray();
    }

    /**
     * 获取主播的公会分成
     * @Cacheable(prefix="guild_host_share", ttl=300, value="_#{hostId}", listener="guild_host_share_update")
     */
    static function getGuildHostSharePercent($hostId = 0)
    {
        if (!$hostId) return 0;
        $where = [
            'host_user_id' => $hostId,
            'status' => GuildHost::STATUS_BIND
        ];
        $data = GuildHost::where($where)->first();
        if (!$data) $percent = 0;
        else {
            $guild = GuildManage::find($data->guild_manage_id);
            $percent = $guild ? $guild->host_share_ratio : 0;
        }
        log_info(__METHOD__ . "=={$hostId}=={$percent}");
        return $percent;
    }

    /**
     * 获取用户等级配置
     * @Cacheable(prefix="setting_user_level", ttl=120, value="_#{levelType}", listener="setting_user_level_update")
     */
    static function getUserLevelSetting($levelType = 1)
    {
        log_info(__METHOD__ . "=={$levelType}");
        $data = SettingUserLevel::where(['level_type' => $levelType, 'flag' => 1])->orderBy('level', 'asc')->get()->toArray();
        $ret = [];
        foreach ($data as $item) {
            $ret[] = [
                'level' => $item['level'],
                'level_value' => $item['number'],
                'chat_coin_setting' => $item['chat_coin_setting'],
                'voice_coin_setting' => $item['voice_coin_setting'],
                'video_coin_setting' => $item['video_coin_setting'],
            ];
        }
        return $ret;
    }

    /**
     * 获取用户等级配置
     * @Cacheable(prefix="setting_user_coin", ttl=120, value="_#{coinField}", listener="setting_user_coin_update")
     */
    static function getCoinSetting($coinField = 'voice_coin_setting')
    {
        log_info(__METHOD__ . "=={$coinField}");
        $data = SettingUserLevel::where(['level_type' => SettingUserLevel::TYPE_CHARM, 'flag' => 1])->orderBy('number', 'desc')->get()->toArray();
        $coinSetArr = [];
        foreach ($data as $item) $coinSetArr[$item[$coinField]] = [
            'charm_limit' => $item['number'],
            'coin' => $item[$coinField],
            'level_limit' => $item['level']
        ];
        array_multisort(array_column($coinSetArr, 'charm_limit'), SORT_ASC, $coinSetArr);
        //私信收费
        if ($coinField == 'chat_coin_setting') {
            // array_unshift($coinSetArr, [
            //     'charm_limit' => 0,
            //     'coin' => 0.0,
            //     'level_limit' => 0
            // ]);
            return array_values($coinSetArr);
        }
        $data = [];
        $coinArr = array_values($coinSetArr);
        for ($coin = $coinArr[0]['coin']; $coin <= 200;) {
            $setting = SettingUserLevel::pickCharmLimitByCoin($coin, $coinArr);
            $data[] = [
                'coin' => $coin,
                'charm_limit' => $setting['charm'],
                'level_limit' => $setting['level'],
            ];
            $coin += 10;
        }
        return $data;
    }

    /**
     * 根据分类条件筛选出主播ID
     * @Cacheable(prefix="host_by_cate", ttl=120, value="_#{hostCate}", listener="host_by_cate_update")
     */
    static function getHostsByCate($hostCate = UserProfile::HOST_CATE_A)
    {
        //自己运营的主播池
        if ($hostCate == UserProfile::HOST_CATE_OFFICIAL) {
            return HostPoolForNew::getValidHosts();
        }
        return Db::table('user_profile')->join('user', function ($join) use ($hostCate) {
            $where = [
                ['status', '=', User::STATUS_OK],
                ['role', UserProfile::ROLE_HOST],
                ['is_official', 0],
                ['host_cate', $hostCate],
            ];
            $join->on('user.id', '=', 'user_profile.user_id')->where($where);
        })->pluck('user_id')->toArray();
    }

    /**
     * 获取禁言状态的用户
     * @Cacheable(prefix="forbidden_user", ttl=120, listener="forbidden_user_update")
     */
    static function getForbiddenUsers()
    {
        return User::where('status', User::STATUS_FORBID)->pluck('id')->toArray();
    }

    /**
     * 获取通话过的用户
     * @Cacheable(prefix="called_users", ttl=120, value="_#{userId}_#{callType}", listener="called_users_update")
     */
    static function getCalledUsers($userId = 0, $callType = VideoCall::CALL_TYPE)
    {
        log_info(__METHOD__ . "=={$userId}");
        $callClass  = $callType == VideoCall::CALL_TYPE ? VideoCall::class : VoiceCall::class;
        $where = [['user_id', $userId]];
        $orWhere = [['chat_user_id', $userId]];
        $calledUserIds = $callClass::where($where)->whereIn('status', CallBase::DONE_STATUS)->pluck('chat_user_id')->toArray();
        $calledUserIds = array_merge($calledUserIds, $callClass::where($orWhere)->whereIn('status', CallBase::DONE_STATUS)->pluck('user_id')->toArray());
        return array_unique($calledUserIds);
    }

    /**
     * 获取聊天过的用户
     * @Cacheable(prefix="chated_users", ttl=120, value="_#{userId}", listener="chated_users")
     */
    static function getChatedUsers($userId = 0)
    {
        log_info(__METHOD__ . "=={$userId}");
        $where = [['user_id', $userId]];
        $orWhere = [['chat_user_id', $userId]];
        $where[] = $orWhere[] = ['msg_num', '>', 1];
        $where[] = $orWhere[] = ['chat_msg_num', '>', 1];
        $logs = UserChat::where($where)->orWhere(function ($query) use ($orWhere) {
            $query->where($orWhere);
        })->select(['chat_user_id', 'user_id'])->get()->toArray();
        $chatedUserIds = [];
        foreach ($logs as $log) {
            $uid = $log['user_id'] == $userId ? $log['chat_user_id'] : $log['user_id'];
            !in_array($uid, $chatedUserIds) && array_push($chatedUserIds, $uid);
        }
        return $chatedUserIds;
    }
}
